#include "TileForwardAnimSolidColourFX.h"

TileForwardAnimSolidColourFX::TileForwardAnimSolidColourFX(ID3D11Device* device)
	:AbstractFX(device, L"FX/TileForwardAnimSolidColour.fxo")
{
	//Create Input Layout
	InitInputLayout(device);
	//Init shader variables
	InitShaderVariablePointers();
}

TileForwardAnimSolidColourFX::~TileForwardAnimSolidColourFX()
{}
	
void TileForwardAnimSolidColourFX::InitInputLayout(ID3D11Device* device)
{
	//Fillout input layout description.
	const D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[] = 
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"WEIGHTS",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"BONEINDICES", 0, DXGI_FORMAT_R8G8B8A8_UINT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	//Create our input layout 	
	CreateInputLayout(device, inputLayoutDesc, 4);
}

void TileForwardAnimSolidColourFX::InitShaderVariablePointers()
{
	worldVar         = effect->GetVariableByName("world")->AsMatrix();
	worldInvTransVar = effect->GetVariableByName("worldInvTrans")->AsMatrix();
	worldViewProjVar = effect->GetVariableByName("worldViewProj")->AsMatrix();

	rtWidthVar  = effect->GetVariableByName("rtWidth")->AsScalar();
	rtHeightVar = effect->GetVariableByName("rtHeight")->AsScalar();

	materialVar        = effect->GetVariableByName("mat");
	eyePosVar          = effect->GetVariableByName("eyePosW")->AsVector();
    direcLightVar	   = effect->GetVariableByName("dLight");
	direcLightCountVar = effect->GetVariableByName("dLightCount")->AsScalar();

	//Tile Forward System
	llbVar   = effect->GetVariableByName("LightListBuffer")->AsShaderResource();
	llibVar  = effect->GetVariableByName("LightListIndexBuffer")->AsShaderResource();
	llsebVar = effect->GetVariableByName("LightListStartEndBuffer")->AsShaderResource();

	//Animation
	boneTransVar = effect->GetVariableByName("boneTransform")->AsMatrix();

	//Solid colour.
	colourVar = effect->GetVariableByName("SolidColour")->AsVector();
	
	//Hemispherical lighting
	hemiColDownVar = effect->GetVariableByName("HemiColDown")->AsVector();
	hemiColRangeVar = effect->GetVariableByName("HemiColRange")->AsVector();
	
	//SSAO
	worldViewVar = effect->GetVariableByName("WorldView")->AsMatrix();
	ssaoMapVar = effect->GetVariableByName("SSAOMap")->AsShaderResource();
	ssaoWorldViewProjTexVar = effect->GetVariableByName("SSAOWorldViewProjTex")->AsMatrix();

	//Environment map
	envMapVar = effect->GetVariableByName("EnvironmentMap")->AsShaderResource();
	
	//Shadow map
	shadowMapVar = effect->GetVariableByName("ShadowMap")->AsShaderResource();
	shadowMapViewVar = effect->GetVariableByName("ShadowMapView")->AsMatrix();
	shadowMapProjVar = effect->GetVariableByName("ShadowMapProj")->AsMatrix();
	shadowMapToTexVar = effect->GetVariableByName("ShadowMapToTex")->AsMatrix();
}

void TileForwardAnimSolidColourFX::SetPerObjectCbuffer(CXMMATRIX& world, 
	CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj,
	Material mat, XMFLOAT3& modelSolidColour, 
		CXMMATRIX& worldView)
{
	worldVar->SetMatrix(reinterpret_cast<const float*>(&world));
	worldInvTransVar->SetMatrix(reinterpret_cast<const float*>(&worldInvTrans));
	worldViewProjVar->SetMatrix(reinterpret_cast<const float*>(&worldViewProj));
	materialVar->SetRawValue(&mat, 0, sizeof(Material));

	colourVar->SetRawValue(&modelSolidColour, 0, sizeof(XMFLOAT3));

	worldViewVar->SetMatrix(reinterpret_cast<const float*>(&worldView));
}

void TileForwardAnimSolidColourFX::SetAnimationBoneTransformArray(XMFLOAT4X4* matArr, unsigned count)
{
	boneTransVar->SetMatrixArray(reinterpret_cast<const float*>(matArr), 0, count);
}

void TileForwardAnimSolidColourFX::SetRTDimensions(unsigned width, unsigned height)
{
	rtWidthVar->SetInt(width);
	rtHeightVar->SetInt(height);
}

void TileForwardAnimSolidColourFX::SetLightListBuffer(ID3D11ShaderResourceView* lightListBuffer)
{
	llbVar->SetResource(lightListBuffer);
}

void TileForwardAnimSolidColourFX::SetLightingData(XMFLOAT3& eye, 
	DirectionalLight* dLights, unsigned dLightCount,
	ID3D11ShaderResourceView* lightListIndexBuffer, 
	ID3D11ShaderResourceView* lightListStartEndBuffer)
{
	eyePosVar->SetRawValue(&eye, 0, sizeof(XMFLOAT3));
	
	//Cap Direc Lights to 3.
	if (dLightCount > MAX_DIRECTIONAL_LIGHT_COUNT)
		dLightCount = MAX_DIRECTIONAL_LIGHT_COUNT;
	direcLightVar->SetRawValue(dLights, 0, sizeof(DirectionalLight) * dLightCount);
	direcLightCountVar->SetInt(dLightCount);

	//Update LLIB, LLSEB
	llibVar->SetResource(lightListIndexBuffer);
	llsebVar->SetResource(lightListStartEndBuffer);
}

void TileForwardAnimSolidColourFX::SetHemisphericalData(XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange)
{
	hemiColDownVar->SetRawValue(&hemiColDown, 0, sizeof(XMFLOAT3));
	hemiColRangeVar->SetRawValue(&hemiColRange, 0, sizeof(XMFLOAT3));
}

void TileForwardAnimSolidColourFX::SetSSAOData(ID3D11ShaderResourceView* ssaoTex, CXMMATRIX &transform)
{
	ssaoMapVar->SetResource(ssaoTex);
	ssaoWorldViewProjTexVar->SetMatrix(reinterpret_cast<const float*>(&transform));
}

void TileForwardAnimSolidColourFX::SetEnvironmentMap(ID3D11ShaderResourceView* envCubeMap)
{
	envMapVar->SetResource(envCubeMap);
}

void TileForwardAnimSolidColourFX::SetShadowMap(ID3D11ShaderResourceView* shadowMap)
{
	shadowMapVar->SetResource(shadowMap);
}

void TileForwardAnimSolidColourFX::SetShadowMapMatricies(CXMMATRIX &view, CXMMATRIX &proj, CXMMATRIX &toTex)
{
	shadowMapViewVar->SetMatrix(reinterpret_cast<const float*>(&view));
	shadowMapProjVar->SetMatrix(reinterpret_cast<const float*>(&proj));
	shadowMapToTexVar->SetMatrix(reinterpret_cast<const float*>(&toTex));
}